<script lang='ts' setup>
import { PropType, reactive, watch } from 'vue'
import { Website } from '@/apis/website/websites.ts'
import { set_website } from '@/apis/website/set_website.ts'
import { date_format } from '@/funcs/date_format.ts'
import { UploadCustomRequestOptions } from 'naive-ui'
import { resources_upload_file } from '@/apis/toolbox/resources/resources_upload_file.ts'

const props = defineProps({
  show: { required: true, type: Boolean },
  index: { required: true, type: Number },
  website: { required: true, type: Object as PropType<Website> }
})

const emits = defineEmits(['update:show', 'saved'])
const state = reactive<{ website: Website, loading: boolean }>({ website: { hostname: '', reverses: [], tls: { enable: true, custom: false, cert_path: '', key_path: '' }, removing: false }, loading: false })

watch(props, async function(_, n) {
  n.show && (state.website = JSON.parse(JSON.stringify(props.website)) as Website)
})

async function close(): Promise<void> {
  emits('update:show', false)
  state.website = { hostname: '', reverses: [], tls: { enable: true, custom: false, cert_path: '', key_path: '' }, removing: false }
}

async function save(): Promise<void> {
  if ('' === state.website.hostname.trim()) {
    window.$message.warning('站点域名不能为空')

    return
  }

  if (0 === state.website.reverses.length) {
    window.$message.warning('反向代理路由配置不能为空，最少需要添加一条配置')

    return
  }

  for (let i = 0; i < state.website.reverses.length; i++) {
    if ('' === state.website.reverses[i].path.trim() || '' === state.website.reverses[i].target.trim()) {
      window.$message.warning('反向代理路由配置错误，匹配路径与目标地址均不可为空')

      return
    }
  }

  state.loading = true
  const response = await set_website(state.website)
  state.loading = false

  if (0 !== response.code) {
    window.$message.error(response.message)

    return
  }

  window.$message.success('保存成功，配置已生效')

  emits('saved', props.index, state.website)
  await close()
}

async function remove_reverse(index: number): Promise<void> {
  state.website.reverses.splice(index, 1)
}

async function custom_upload_cert(options: UploadCustomRequestOptions): Promise<void> {
  const formData = new FormData()
  formData.set('path', '/website/' + date_format(new Date().getTime(), 'yyyy-MM-dd') + '/')
  formData.append("file", options.file.file as File)

  const response = await resources_upload_file(formData)
  if (0 !== response.code) {
    window.$message.error(response.message)
    options.onError()

    return
  }

  window.$message.success('上传成功')
  state.website.tls.cert_path = response.data.path
}

async function custom_upload_key(options: UploadCustomRequestOptions): Promise<void> {
  const formData = new FormData()
  formData.set('path', '/website/' + date_format(new Date().getTime(), 'yyyy-MM-dd') + '/')
  formData.append("file", options.file.file as File)

  const response = await resources_upload_file(formData)
  if (0 !== response.code) {
    window.$message.error(response.message)
    options.onError()

    return
  }

  window.$message.success('上传成功')
  state.website.tls.key_path = response.data.path
}
</script>

<template>
  <n-modal :closable='false' :close-on-esc='false' :mask-closable='false' :show='props.show' class='website-set-modal' transform-origin='center'>
    <n-card>
      <n-space vertical>
        <div>
          <n-space vertical>
            <n-divider>基础配置</n-divider>
            <div>
              <n-input-group>
                <n-input-group-label size='small'>
                  <n-text>域名</n-text>
                </n-input-group-label>
                <n-input v-model:value='state.website.hostname' placeholder='站点域名，不可为空，不可携带协议信息与端口信息' size='small' />
              </n-input-group>
            </div>
            <n-divider>TLS配置</n-divider>
            <div>
              <n-space align='center'>
                <n-text>启用TLS连接</n-text>
                <n-switch v-model:value='state.website.tls.enable' size='small' />
                <n-text>自定义TLS证书</n-text>
                <n-switch v-model:value='state.website.tls.custom' :disabled='!state.website.tls.enable' size='small' />
              </n-space>
            </div>
            <div class='website-tls-files'>
              <n-space :wrap-item='false' align='center'>
                <div class='width-05'>
                  <n-input-group>
                    <n-input-group-label size='small'>证书</n-input-group-label>
                    <n-input v-model:value='state.website.tls.cert_path' :disabled='!state.website.tls.enable || !state.website.tls.custom' class='width-max' placeholder='输入证书路径或上传' size='small' />
                    <n-upload :custom-request='custom_upload_cert' :disabled='!state.website.tls.enable || !state.website.tls.custom' :show-file-list='false' action='/api/toolbox/resources/upload'>
                      <n-button size='small'>上传证书文件</n-button>
                    </n-upload>
                  </n-input-group>
                </div>
                <div class='flex-max'>
                  <n-input-group>
                    <n-input-group-label size='small'>私钥</n-input-group-label>
                    <n-input v-model:value='state.website.tls.key_path' :disabled='!state.website.tls.enable || !state.website.tls.custom' class='width-max' placeholder='输入私钥路径或上传' size='small' />
                    <n-upload :custom-request='custom_upload_key' :disabled='!state.website.tls.enable || !state.website.tls.custom' :show-file-list='false' action='/api/toolbox/resources/upload'>
                      <n-button size='small'>上传私钥文件</n-button>
                    </n-upload>
                  </n-input-group>
                </div>
              </n-space>
            </div>
            <n-divider>路由配置</n-divider>
            <template v-for='(reverse, index) in state.website.reverses' :key='index'>
              <div>
                <n-space :wrap-item='false' align='center'>
                  <div class='flex-max'>
                    <n-input-group>
                      <n-input-group-label size='small'>匹配路径</n-input-group-label>
                      <n-input v-model:value='reverse.path' size='small' />
                    </n-input-group>
                  </div>
                  <div class='flex-max'>
                    <n-input-group>
                      <n-input-group-label size='small'>目标地址</n-input-group-label>
                      <n-input v-model:value='reverse.target' size='small' />
                    </n-input-group>
                  </div>
                  <div>
                    <n-button size='small' type='error' @click='remove_reverse(index)'>移除</n-button>
                  </div>
                </n-space>
              </div>
            </template>
            <div>
              <n-button class='width-max' size='small' type='primary' @click="state.website.reverses.push({path: '', target: ''})">添加路由</n-button>
            </div>
          </n-space>
        </div>
        <n-space align='center' justify='center'>
          <n-button size='small' type='error' @click='close'>取消</n-button>
          <n-button :loading='state.loading' size='small' type='primary' @click='save'>保存</n-button>
        </n-space>
      </n-space>
    </n-card>
  </n-modal>
</template>

<style scoped>

.website-set-modal {
  width: 85vw;
  height: 800px;
  overflow-y: auto;
}

.website-tls-files .n-upload {
  width: auto;
}
</style>
